package com.jweb.framework.http.interceptors;

import java.sql.Timestamp;
import java.util.Enumeration;
import java.util.Locale;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.web.servlet.support.RequestContextUtils;

import com.jweb.framework.core.ContextEx;
import com.jweb.framework.core.CoreException;
import com.jweb.framework.core.User;
import com.jweb.framework.core.channel.ChannelContext;
import com.jweb.framework.core.channel.interceptors.ContextInterceptor;
import com.jweb.framework.core.support.TRACER;
import com.jweb.framework.http.support.SmartLocaleResolver;

/**
 * 修改人： Thomas
 * 修改内容：新增 
 * 类说明：HTTP渠道接收报文拦截器，待扩展
 */
public class ServletContextInterceptor extends ContextInterceptor<HttpServletRequest, HttpServletResponse>{
	
	private String[] sessionVariables = {"CAPTCHA"} ;
	
	private String[] oneTimeSessionAttributes = {"CAPTCHA"};
	
	private ContextProcessor contextProcessor = new DefaultContextProcessor();

	public void setSessionVariables(String[] sessionVariables) {
		String arr[] = new String[sessionVariables.length + 1];
		arr[0] = "CAPTCHA";
		// 源数组 ，源数组中的起始位置，目标数组，目标数据中的起始位置，要复制的数组元素的位置
		System.arraycopy(sessionVariables, 0, arr, 1, sessionVariables.length);
		
		this.sessionVariables = sessionVariables;
	}

	public void setOneTimeSessionAttributes(String[] oneTimeSessionAttributes) {
		String arr[] = new String[oneTimeSessionAttributes.length + 1];
		arr[0] = "CAPTCHA";
		System.arraycopy(oneTimeSessionAttributes, 0, arr, 1, oneTimeSessionAttributes.length);
		
		this.oneTimeSessionAttributes = oneTimeSessionAttributes;
	}

	public void setContextProcessor(ContextProcessor contextProcessor) {
		this.contextProcessor = contextProcessor;
	}
				   
	protected void resolveAttributes(
			ChannelContext<HttpServletRequest, HttpServletResponse> channelContext,
			ContextEx contextEx) {
		
		HttpServletRequest request = channelContext.getRequest();
		contextEx.setLocale(RequestContextUtils.getLocale(request));
		
		if(this.contextProcessor != null){
			this.contextProcessor.resolveAttributes(contextEx, request);
		}
		
		HttpSession httpSession = request.getSession(false);
		if(httpSession!=null){
			
			contextEx.setSessionId(httpSession.getId());
			TRACER.trace("session:{},created:{},last-access:{},now:{}",new Object[]{
					httpSession.getId(),
					new Timestamp(httpSession.getCreationTime()),
					new Timestamp(httpSession.getLastAccessedTime()),
					new Timestamp(System.currentTimeMillis())
			});
			
			User user = (User) httpSession.getAttribute("user");
			if(user!=null){
				contextEx.setUser(user);
			}
			
			synchronized(httpSession){
				for(String str : this.oneTimeSessionAttributes){
					Object obj1 = contextEx.getData(str);
					
					if(obj1!=null){
						Object obj2 = httpSession.getAttribute(str);
						if(obj2!=null){
							contextEx.setSessionAttribute(str, obj2);
							httpSession.removeAttribute(str);
						}
					}
					
				}
				for(Enumeration enum1 = httpSession.getAttributeNames() ; enum1.hasMoreElements();){
					String str = (String) enum1.nextElement();
					if(!"user".equals(str)){
						contextEx.setSessionAttribute(str, httpSession.getAttribute(str));
					}
				}
			}
		}
	}

	protected void postAttributes(
			ChannelContext<HttpServletRequest, HttpServletResponse> channelContext,
			ContextEx contextEx) {
		
		HttpServletRequest request = channelContext.getRequest();
		User user1 = contextEx.getUser();
		
		HttpSession httpSession = request.getSession(false);
		if(user1!=null){
			synchronized(user1){
				if(!user1.isLogined()){
					if(httpSession!=null){
						httpSession.invalidate();
						TRACER.trace("user {} logout", new String[]{user1.getUniqueId()});
						return ;
					}
				}
				
				User user2 = (httpSession==null ? null : (User)httpSession.getAttribute("user"));
				if(user2!=null){
					if(user1!=user2){
						httpSession.invalidate();
						contextEx.setException(new CoreException("user_switch_unexpected"));
						return ;
					}
					httpSession.setAttribute("user", user1);
				}
				else{
					Locale locale = null;
					if(httpSession!=null){
						locale = (Locale) httpSession.getAttribute(SmartLocaleResolver.LOCALE_ATTRIBUTE_NAME);
						httpSession.invalidate();
					}
					
					httpSession = request.getSession(true);
					httpSession.setAttribute("user", user1);
					if(locale!=null){
						httpSession.setAttribute(SmartLocaleResolver.LOCALE_ATTRIBUTE_NAME, locale);
					}
				}
			}
		}
		
		if(this.sessionVariables!=null && this.sessionVariables.length>0){
			if(httpSession == null){
				httpSession = request.getSession(true);
			}
			for(String str : this.sessionVariables){
				Object obj = contextEx.getVariable(str);
				if(obj!=null){
					httpSession.setAttribute(str, obj);
				}
			}
		}
		
		if(this.contextProcessor!=null){
			this.contextProcessor.postAttributes(contextEx, request);
		}
		
		if(httpSession != null && isBoolean(httpSession)){
			httpSession.invalidate();
		}
		
	}

	private boolean isBoolean(HttpSession httpSession) {
		return !httpSession.getAttributeNames().hasMoreElements();
	}
	
}
